package inventory

import (
	"LogisticsPort/model"
	"LogisticsPort/sql"
	"errors"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"strconv"
)

func inventorySales(inventory *gin.RouterGroup) {
	//销售
	sales := inventory.Group("/sales")
	{
		sales.POST("/subAdd", inventorySalesAdd)
		sales.POST("/subUpdate", inventorySalesUpdate)
		sales.POST("/subReturn", inventorySalesReturn)
		sales.GET(sql.RequestData, inventorySalesData)
		sales.GET(sql.RequestList, inventorySalesList)
		sales.GET(sql.RequestDelete, inventorySalesDelete)
	}
}

// InventorySalesAdd /** 商品销售
func inventorySalesAdd(c *gin.Context) {
	sql.HttpHandle(sql.ADD, c, func(db *gorm.DB) (*gorm.DB, interface{}) {
		var bean model.InventorySalesOrder
		if err := c.BindJSON(&bean); err != nil {
			db.Error = err
			return db, nil
		}
		var tx = db.Begin()

		err := tx.Create(&bean).Error
		if err != nil {
			tx.Callback()
			db.Error = err
			return db, nil
		}

		for _, product := range bean.InventorySalesProduct {
			if err := tx.Model(&model.Inventory{}).
				Where("id = ?", product.InventoryId).
				Updates(map[string]interface{}{
					"inventory_number": gorm.Expr("inventory_number - ?", product.SalesNumber),
					"inventory_weight": gorm.Expr("inventory_weight - ?", product.SalesWeight),
				}).Error; err != nil {
				tx.Rollback()
				db.Error = err
				return db, nil
			}
		}
		tx.Commit()
		return db, bean
	})
}

func inventorySalesUpdate(c *gin.Context) {
	sql.HttpHandle(sql.ADD, c, func(db *gorm.DB) (*gorm.DB, interface{}) {
		var bean model.InventorySalesOrder
		if err := c.BindJSON(&bean); err != nil {
			db.Error = err
			return db, nil
		}
		var tx = db.Begin()
		for _, product := range bean.InventorySalesProduct {

			// 1、查询老数据
			var oldProductData model.InventorySalesProduct
			err := tx.Model(&model.InventorySalesProduct{}).
				Where("inventory_sales_product.id = ?", product.ID).
				First(&oldProductData).Error
			if err != nil {
				tx.Rollback()
				return tx, nil
			}
			// 2、对库存进行修改
			err = tx.Model(&model.Inventory{}).
				Where("id = ?", product.InventoryId).
				Updates(map[string]interface{}{
					"inventory_number": gorm.Expr("inventory_number + ?", oldProductData.SalesNumber),
					"inventory_weight": gorm.Expr("inventory_weight + ?", oldProductData.SalesNumber),
				}).Error
			if err != nil {
				tx.Rollback()
				db.Error = err
				return db, nil
			}
		}
		// 3、修改销售数据
		if err := tx.
			Session(&gorm.Session{FullSaveAssociations: true}).
			Updates(&bean).Error; err != nil {
			tx.Callback()
			return tx, nil
		}
		// 4、修改销售库存
		for _, product := range bean.InventorySalesProduct {
			if err := tx.Model(&model.Inventory{}).
				Where("id = ?", product.InventoryId).
				Updates(map[string]interface{}{
					"inventory_number": gorm.Expr("inventory_number - ?", product.SalesNumber),
					"inventory_weight": gorm.Expr("inventory_weight - ?", product.SalesWeight),
				}).Error; err != nil {
				tx.Rollback()
				db.Error = err
				return db, nil
			}
		}

		tx.Commit()
		return db, bean
	})
}

// inventorySalesReturn /** 销售退货
func inventorySalesReturn(c *gin.Context) {
	sql.HttpHandle(sql.ADD, c, func(db *gorm.DB) (*gorm.DB, interface{}) {
		var bean model.InventorySalesOrder
		if err := c.BindJSON(&bean); err != nil {
			db.Error = err
			return db, nil
		}
		var tx = db.Begin()
		if err := tx.Create(&bean); err != nil {
			tx.Callback()
			return tx, nil
		}
		for _, product := range bean.InventorySalesProduct {
			if err := tx.Model(&model.Inventory{}).
				Where("id = ?", product.InventoryId).
				Updates(map[string]interface{}{
					"inventory_number": gorm.Expr("inventory_number + ?", product.SalesNumber),
					"inventory_weight": gorm.Expr("inventory_weight + ?", product.SalesWeight),
				}).Error; err != nil {
				tx.Rollback()
				db.Error = err
				return db, nil
			}
		}
		tx.Commit()
		return db, bean
	})

}

func inventorySalesList(c *gin.Context) {
	sql.HttpList(c, &[]model.InventorySalesOrder{}, func(db *gorm.DB) *gorm.DB {
		start := c.Query("startTime")
		end := c.Query("endTime")
		if start != "" {
			db = db.Where("date >= ? ", start+" 00:00:00")
		}
		if end != "" {
			db = db.Where("date <= ? ", end+" 23:59:59")
		}
		db = db.
			Select("inventory_sales_order.*,customer.name,seller.seller_name").
			Joins("left join customer ON customer.id = inventory_sales_order.customer_id").
			Joins("left join seller ON seller.id = inventory_sales_order.seller_id").
			Preload("InventorySalesProduct", func(db *gorm.DB) *gorm.DB {
				db = db.Select("inventory_sales_product.*," +
					"product.factory_no,product.product_name,product.specification," +
					"purchase_product.contract_no,purchase_product.container_no," +
					"inventory.warehouse,inventory.supplier," +
					"customer.name," +
					"seller.seller_name").
					Joins("left join product ON product.id = inventory_sales_product.product_id").
					Joins("left join purchase_product on purchase_product.id = inventory_sales_product.purchase_product_id").
					Joins("left join inventory ON inventory.id = inventory_sales_product.product_id").
					Joins("left join customer ON customer.id = inventory_sales_product.customer_id").
					Joins("left join seller ON seller.id = inventory_sales_product.seller_id").
					Order("date DESC")
				return db
			}).
			Preload("BankStatement", func(db *gorm.DB) *gorm.DB {
				db = db.Where("bank_statement.function = ?", "销售").
					Select("bank_statement.*,bank_account.bank,bank_account.account_name,bank_account.card_number,bank_flow.date").
					Joins("left join bank_account ON bank_statement.account_id = bank_account.id").
					Joins("left join bank_flow ON bank_statement.bank_flow_id = bank_flow.id")
				return db
			}).
			Order("date DESC")
		return db
	})
}

func inventorySalesData(c *gin.Context) {
	sql.HttpHandle(sql.GET, c, func(db *gorm.DB) (*gorm.DB, interface{}) {
		var bean model.InventorySalesOrder
		var id = c.Query("id")
		if id == "" {
			db.Error = errors.New(sql.ErrorParams)
			return db, nil
		}
		db = db.
			Where("inventory_sales_order.id = ?", id).
			Select("inventory_sales_order.*,customer.name,seller.seller_name").
			Joins("left join customer ON customer.id = inventory_sales_order.customer_id").
			Joins("left join seller ON seller.id = inventory_sales_order.seller_id").
			Preload("InventorySalesProduct", func(db *gorm.DB) *gorm.DB {
				db = db.Select("inventory_sales_product.*," +
					"product.factory_no,product.product_name,product.specification," +
					"purchase_product.contract_no,purchase_product.container_no," +
					"inventory.warehouse,inventory.supplier," +
					"customer.name," +
					"seller.seller_name").
					Joins("left join product ON product.id = inventory_sales_product.product_id").
					Joins("left join purchase_product on purchase_product.id = inventory_sales_product.purchase_product_id").
					Joins("left join inventory ON inventory.id = inventory_sales_product.inventory_id").
					Joins("left join customer ON customer.id = inventory_sales_product.customer_id").
					Joins("left join seller ON seller.id = inventory_sales_product.seller_id").
					Order("date DESC")
				return db
			})
		db.First(&bean)
		return db, bean
	})
}

func inventorySalesDelete(c *gin.Context) {
	sql.HttpHandle(sql.DELETE, c, func(db *gorm.DB) (*gorm.DB, interface{}) {
		idStr := c.Query("id")
		id, err := strconv.Atoi(idStr)
		if err != nil {
			db.Error = errors.New(sql.ErrorParams)
			return db, nil
		}
		var tx = db.Begin()
		var bean model.InventorySalesOrder
		err = tx.Where("inventory_sales_order.id = ?", id).
			Preload("InventorySalesProduct").
			First(&bean).Error
		if err != nil {
			tx.Callback()
			tx.Error = err
			return tx, nil
		}

		for _, product := range bean.InventorySalesProduct {
			err = tx.Model(&model.Inventory{}).
				Where("id = ?", product.InventoryId).
				Updates(map[string]interface{}{
					"inventory_number": gorm.Expr("inventory_number + ?", product.SalesNumber),
					"inventory_weight": gorm.Expr("inventory_weight + ?", product.SalesWeight),
				}).Error
			if err != nil {
				tx.Rollback()
				tx.Error = err
				return tx, nil
			}
		}

		tx = tx.Select(clause.Associations).
			Delete(&model.InventorySalesOrder{
				Model: gorm.Model{ID: uint(id)},
			})
		tx.Commit()
		return tx, nil
	})
}
